﻿using System;
using System.Collections.Generic;
using System.Xml.XPath;
using DotNetNuke.Entities.Tabs;
using DotNetNuke.UI.Skins;
using DotNetNuke.UI.WebControls;

namespace BrandonHaynes.Providers.Navigation
	{
	/// <summary>
	/// A base class for templated menus, providing basic databinding support functionality
	/// </summary>
	public class MenuTemplate : SkinObjectBase
		{
		public MenuTemplate()
			: base()
			{ TabMap = Extensions.GetTabMap(); }

		public MenuNode DataSource { get; set; }
		private Dictionary<int, TabInfo> TabMap { get; set; }

		#region Protected DataBinding Helper Methods

		/// <summary>
		/// Returns the root tab associated with this template
		/// </summary>
		protected TabInfo RootTab
			{ get { return GetTab(RootNode.ID.ToString()); } }

		/// <summary>
		/// Returns the root node associated with this template
		/// </summary>
		protected MenuNode RootNode
			{ get { return DataSource; } }

		/// <summary>
		/// Given a DNNNode, int, or IXPathNavigable argument, returns the associated tab
		/// </summary>
		protected virtual TabInfo GetTab(object identifier)
			{
			TabInfo tab = null;

			var nodeIdentifier = identifier as DNNNode;
			if (nodeIdentifier != null) tab = GetTab(nodeIdentifier);

			var intIdentifier = identifier as Nullable<int>;
			if (intIdentifier != null) tab = GetTab(intIdentifier.Value);

			var xmlIdentifier = identifier as IXPathNavigable;
			if (xmlIdentifier != null) tab = GetTab(xmlIdentifier);

			return tab;
			}

		/// <summary>
		/// Given an xml fragment, returns an associated tab (as selected by the fragment's @id attribute)
		/// </summary>
		protected virtual TabInfo GetTab(IXPathNavigable menuXml)
			{ return GetTab(menuXml.CreateNavigator().GetAttribute("id", string.Empty)); }

		/// <summary>
		/// Given a DNNNode, returns the Tab associated with that node
		/// </summary>
		protected TabInfo GetTab(DNNNode node)
			{ return GetTab(node.ID); }

		/// <summary>
		/// Returns the tab associated with the tabId
		/// </summary>
		protected virtual TabInfo GetTab(int tabId)
			{
			TabInfo tab;
			return TabMap.TryGetValue(tabId, out tab) ? tab : null;
			}

		/// <summary>
		/// Given a MenuNode, returns an enumeration of child MenuNodes associated therewith
		/// </summary>
		/// <param name="menuNode"></param>
		/// <returns></returns>
		protected static IEnumerable<MenuNode> ChildMenuNodes(MenuNode menuNode)
			{ return menuNode.MenuNodes.ToEnumerable(); }

		#endregion

		private TabInfo GetTab(string id)
			{
			int tabId;
			return int.TryParse(id, out tabId) ?
				GetTab(tabId) : null;
			}
		}
	}
